home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / net_src.arc / ax25.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-08  |  13.3 KB  |  426 lines

  1. /* Low level AX.25 frame processing - address header */
  2.  
  3. #include <stdio.h>
  4. #include <time.h>
  5. #include "config.h"
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "iface.h"
  9. #include "timer.h"
  10. #include "arp.h"
  11. #include "slip.h"
  12. #include "ax25.h"
  13. #include "lapb.h"
  14. #include <ctype.h>
  15. #include "heard.h"
  16.  
  17. #ifdef MULPORT
  18. extern int mport;
  19. #endif
  20.  
  21. /* AX.25 broadcast address: "QST-0" in shifted ascii */
  22. struct ax25_addr ax25_bdcst = {
  23.      'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1,
  24.      ('0'<<1) | E,
  25. };
  26. #ifdef SID2
  27. struct ax25_addr bbscall;
  28. #endif
  29. char axbdcst[AXALEN];    /* Same thing, network format */
  30. struct ax25_addr mycall;
  31. int digipeat = 1;   /* Controls digipeating */
  32.  
  33. /* Send IP datagrams across an AX.25 link */
  34. int
  35. ax_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  36. struct mbuf *bp;
  37. struct interface *interface;
  38. int32 gateway;
  39. char precedence;
  40. char delay;
  41. char throughput;
  42. char reliability;
  43. {
  44.      char *hw_addr,*res_arp();
  45.      struct ax25_cb *axp,*find_ax25(),*open_ax25();
  46.      struct ax25 addr;
  47.      struct ax25_addr destaddr;
  48.      struct mbuf *tbp;
  49.      extern int16 axwindow;
  50.      void ax_incom();
  51.      int16 size,bsize,seq;
  52.  
  53.      if((hw_addr = res_arp(interface,ARP_AX25,gateway,bp)) == NULLCHAR)
  54.           return 0; /* Wait for address resolution */
  55.  
  56.      if(delay || (!reliability && (interface->flags == DATAGRAM_MODE))){
  57.           /* Use UI frame */
  58.           return (*interface->output)(interface,hw_addr,
  59.                interface->hwaddr,PID_FIRST|PID_LAST|PID_IP,bp);
  60.      }
  61.      /* Reliability is needed; use I-frames in AX.25 connection */
  62.      memcpy(destaddr.call,hw_addr,ALEN);
  63.      destaddr.ssid = hw_addr[ALEN];
  64.  
  65.      if((axp = find_ax25(&destaddr)) == NULLAX25 || (axp->state != CONNECTED && axp->state!=RECOVERY)){
  66.           /*NOTE: ADDED W9NK's SABM FIX OF && AXP->STATE!=RECOVERY GRC*/
  67.           /* Open a new connection or reinitialize the old one */
  68.           atohax25(&addr,hw_addr,(struct ax25_addr *)interface->hwaddr);
  69.           axp = open_ax25(&addr,axwindow,ax_incom,NULLVFP,NULLVFP,interface,(char *)0);
  70.           if(axp == NULLAX25){
  71.                free_p(bp);
  72.                return -1;
  73.           }
  74.      }
  75.      /* If datagram is too big for one frame, send all but the last with
  76.       * the extension PID. Note: the copy to a new buf is necessary because
  77.       * AX.25 may continue retransmitting the frame after a local TCB has
  78.       * gone away, and using the buf directly would cause heap garbage to be
  79.       * transmitted. Besides, nobody would ever use AX.25 anywhere
  80.       * high performance is needed anyway...
  81.       */
  82.      bsize = len_mbuf(bp);
  83.      seq = 0;
  84.      while(bsize != 0){
  85.           size = min(bsize,axp->paclen);
  86.           /* Allocate buffer, allowing space for PID */
  87.           if((tbp = alloc_mbuf(size + 1)) == NULLBUF)
  88.                break;         /* out of memory! */
  89.           *tbp->data = PID_IP;
  90.           if(seq++ == 0)
  91.                *tbp->data |= PID_FIRST;  /* First in sequence */
  92.           if(size == bsize)
  93.                *tbp->data |= PID_LAST;       /* That's all of it */
  94.           /* else more to follow */
  95.  
  96.           tbp->cnt = 1;
  97.           tbp->cnt += pullup(&bp,tbp->data + 1,size);
  98.           send_ax25(axp,tbp);
  99.           bsize -= size;
  100.      }
  101.      free_p(bp);    /* Shouldn't be necessary */
  102.      return 0;
  103. }
  104. /* Add AX.25 link header and send packet.
  105.  * Note that the calling order here must match ec_output
  106.  * since ARP also uses it.
  107.  */
  108. int
  109. ax_output(interface,dest,source,pid,data)
  110. struct interface *interface;
  111. char *dest;         /* Destination AX.25 address (7 bytes, shifted) */
  112.                /* Also includes digipeater string */
  113. char *source;       /* Source AX.25 address (7 bytes, shifted) */
  114. char pid;      /* Protocol ID */
  115. struct mbuf *data;  /* Data field (follows PID) */
  116. {
  117.      struct mbuf *abp,*cbp,*htonax25();
  118.      struct ax25 addr;
  119.  
  120.      /* Allocate mbuf for control and PID fields, and fill in */
  121.      if((cbp = pushdown(data,2)) == NULLBUF){
  122.           free_p(data);
  123.           return -1;
  124.      }
  125.      cbp->data[0] = UI;
  126.      cbp->data[1] = pid;
  127.  
  128.      atohax25(&addr,dest,(struct ax25_addr *)source);
  129.      if((abp = htonax25(&addr,cbp)) == NULLBUF){
  130.           free_p(cbp);   /* Also frees data */
  131.           return -1;
  132.      }
  133.      /* This shouldn't be necessary because redirection has already been
  134.       * done at the IP router layer, but just to be safe...
  135.       */
  136.      if(interface->forw != NULLIF)
  137.           return (*interface->forw->raw)(interface->forw,abp);
  138.      else
  139.           return (*interface->raw)(interface,abp);
  140. }
  141. /* Process incoming AX.25 packets.
  142.  * After optional tracing, the address field is examined. If it is
  143.  * directed to us as a digipeater, repeat it.  If it is addressed to
  144.  * us or to QST-0, kick it upstairs depending on the protocol ID.
  145.  */
  146. int
  147. ax_recv(interface,bp)
  148. struct interface *interface;
  149. struct mbuf *bp;
  150. {
  151. #ifdef MULPORT
  152.      struct interface *repeater();
  153. #endif
  154.      void arp_input();
  155.      int ip_route();
  156.      struct ax25_addr *ap;
  157.      struct mbuf *htonax25(),*hbp;
  158.      char multicast;
  159.      int nrnodes = 0;
  160.      char control;
  161.      struct ax25 hdr;
  162.      struct ax25_cb *axp,*find_ax25(),*cr_ax25();
  163.      struct ax25_addr ifcall;
  164.      extern struct ax25_addr nr_nodebc ;
  165. /* heard stuff */
  166.      struct heard_stuff *hp;
  167.      extern struct ax25_heard heard;
  168.      int16 type;
  169.      int16 prev, curr;
  170. /* heard stuff */
  171.  
  172.      /* Use the address associated with this interface */
  173.      memcpy(ifcall.call,interface->hwaddr,ALEN);
  174.      ifcall.ssid = interface->hwaddr[ALEN];
  175.  
  176.      /* Pull header off packet and convert to host structure */
  177.      if(ntohax25(&hdr,&bp) < 0){
  178.           /* Something wrong with the header */
  179.           free_p(bp);
  180.           return;
  181.      }
  182. /* heard stuff */
  183.     if (heard.enabled) {
  184.         /* scan heard list.  if not there, add it */
  185.         prev = -1;
  186.         curr = heard.first;
  187.         while (1) {
  188.             if (curr != -1) {
  189.                 hp = &heard.list[curr];
  190.                 if (addreq(&hp->info.source, &hdr.source)) {
  191.                     hp->htime = time(NULL);
  192.                     /* if not the first, make it so */
  193.                     if (prev != -1) {
  194.                         heard.list[prev].next = hp->next;
  195.                         hp->next = heard.first;
  196.                         heard.first = curr;
  197.                     }
  198.                     break;
  199.                 }
  200.             }
  201.  
  202.             /* if the last one, add another if room, or overwrite it */
  203.             if (curr == -1 || hp->next == -1) {
  204.                 /* not in heard list, add it.  if no room, bump oldest */
  205.                 if (heard.cnt < MAX_HEARD) {
  206.                     heard.list[heard.cnt].next = heard.first;
  207.                     heard.first = heard.cnt;
  208.                     hp = &heard.list[heard.cnt++];
  209.                 } else {
  210.                     heard.list[prev].next = -1;
  211.                     heard.list[curr].next = heard.first;
  212.                     heard.first = curr;
  213.                     hp = &heard.list[curr];
  214.                 }
  215.                 hp->flags = 0;
  216.                 memcpy(&hp->info, &hdr, sizeof(struct ax25));
  217.                 hp->htime = time(NULL);
  218.                 break;
  219.             }
  220.     
  221.             prev = curr;
  222.             curr = hp->next;
  223.         }
  224.         
  225.         /* figure out what the other station is running */
  226.         if (bp->cnt >= 2) {
  227.             type = ftype(*bp->data);
  228.             if(type == I || type == UI){    
  229.                 switch(*(bp->data + 1) & 0x3f){
  230.                 case PID_ARP:
  231.                     hp->flags |= HEARD_ARP;
  232.                     break;
  233.                 case PID_NETROM:
  234.                     hp->flags |= HEARD_NETROM;
  235.                     break;
  236.                 case PID_IP:
  237.                     hp->flags |= HEARD_IP;
  238.                     break;
  239.                 }
  240.             }
  241.         }
  242.     } else {
  243.         hp = NULL;
  244.     }
  245. /* heard stuff */
  246.      /* Scan, looking for our call in the repeater fields, if any.
  247.       * Repeat appropriate packets.
  248.       */
  249.      for(ap = &hdr.digis[0]; ap < &hdr.digis[hdr.ndigis]; ap++){
  250.           if(ap->ssid & REPEATED)
  251.                continue; /* Already repeated */
  252.           /* Check if packet is directed to us as a digipeater */
  253.           if(digipeat && addreq(ap,&ifcall)){
  254.                /* Yes, kick it back out */
  255. #ifdef MULPORT
  256. /****************************************************************************
  257. *                 Multiport repeater hack by KE4ZV                          *
  258. ****************************************************************************/
  259.           if (mport){
  260.               interface=repeater(ap,interface,&hdr);
  261.              }
  262. /****************************************************************************
  263. *                  Multiport repeater hack ends                             *
  264. ****************************************************************************/
  265. #endif
  266.                ap->ssid |= REPEATED;
  267.                if((hbp = htonax25(&hdr,bp)) != NULLBUF){
  268.                     if(interface->forw != NULLIF)
  269.                          (*interface->forw->raw)(interface->forw,hbp);
  270.                     else
  271.                          (*interface->raw)(interface,hbp);
  272.                     bp = NULLBUF;
  273.                }
  274.           }
  275.           free_p(bp);    /* Dispose if not forwarded */
  276.           return;
  277.      }
  278.      /* Packet has passed all repeaters, now look at destination */
  279.      if(addreq(&hdr.dest,&ax25_bdcst)){
  280.           multicast = 1; /* Broadcast packet */
  281. #ifdef SID2
  282.      } else if(addreq(&hdr.dest,&ifcall) || addreq(&hdr.dest,&bbscall)){
  283. #else
  284.      } else if(addreq(&hdr.dest,&ifcall)){
  285. #endif
  286.           multicast = 0; /* Packet directed at us */
  287.      } else if(addreq(&hdr.dest,&nr_nodebc)){
  288.           nrnodes = 1 ;
  289.      } else {
  290.           /* Not for us */
  291.           free_p(bp);
  292.           return;
  293.      }
  294.      if(bp == NULLBUF){
  295.           /* Nothing left */
  296.           return;
  297.      }
  298.      /* Sneak a peek at the control field. This kludge is necessary because
  299.       * AX.25 lacks a proper protocol ID field between the address and LAPB
  300.       * sublayers; a control value of UI indicates that LAPB is to be
  301.       * bypassed.
  302.       */
  303.      control = *bp->data & ~PF;
  304.      if(uchar(control) == UI){
  305.           char pid;
  306.  
  307.           (void) pullchar(&bp);
  308.           if(pullup(&bp,&pid,1) != 1)
  309.                return;        /* No PID */
  310.           /* NET/ROM is very poorly layered. The meaning of the stuff
  311.            * following the PID of CF depends on what's in the AX.25 dest
  312.            * field.
  313.            */
  314.           if(nrnodes){
  315.                if(uchar(pid) == (PID_NETROM | PID_FIRST | PID_LAST))
  316.                     nr_nodercv(interface,&hdr.source,bp) ;
  317.                else      /* regular UI packets to "nodes" aren't for us */
  318.                     free_p(bp) ;
  319.                return ;
  320.           }
  321.           /* Handle packets. Multi-frame messages are not allowed */
  322.           switch(pid & (PID_FIRST | PID_LAST | PID_PID)){
  323.           case (PID_IP | PID_FIRST | PID_LAST):
  324.                ip_route(bp,multicast);
  325.                break;
  326.           case (PID_ARP | PID_FIRST | PID_LAST):
  327.                arp_input(interface,bp);
  328.                break;
  329.           default:
  330.                free_p(bp);
  331.                break;
  332.           }
  333.           return;
  334.      }
  335.      /* Everything from here down is LAPB stuff, so drop anything
  336.       * not directed to us:
  337.       */
  338.  
  339.      if (multicast || nrnodes) {
  340.           free_p(bp) ;
  341.           return ;
  342.      }
  343.  
  344.      /* Find the source address in hash table */
  345.      if((axp = find_ax25(&hdr.source)) == NULLAX25){
  346.           /* Create a new ax25 entry for this guy,
  347.            * insert into hash table keyed on his address,
  348.            * and initialize table entries
  349.            */
  350.           if((axp = cr_ax25(&hdr.source)) == NULLAX25){
  351.                free_p(bp);
  352.                return;
  353.           }
  354.           axp->interface = interface;
  355.           /* Swap source and destination, reverse digi string */
  356.           ASSIGN(axp->addr.dest,hdr.source);
  357.           ASSIGN(axp->addr.source,hdr.dest);
  358.           if(hdr.ndigis > 0){
  359.                int i,j;
  360.  
  361.                /* Construct reverse digipeater path */
  362.                for(i=hdr.ndigis-1,j=0;i >= 0;i--,j++){
  363.                     ASSIGN(axp->addr.digis[j],hdr.digis[i]);
  364.                     axp->addr.digis[j].ssid &= ~(E|REPEATED);
  365.                }
  366.                /* Scale timers to account for extra delay */
  367.                axp->t1.start *= hdr.ndigis+1;
  368.                axp->t2.start *= hdr.ndigis+1;
  369.                axp->t3.start *= hdr.ndigis+1;
  370.           }
  371.           axp->addr.ndigis = hdr.ndigis;
  372.      }
  373.      if(hdr.cmdrsp == UNKNOWN)
  374.           axp->proto = V1;    /* Old protocol in use */
  375.      else
  376.           axp->proto = V2;
  377.  
  378.      lapb_input(axp,hdr.cmdrsp,bp);
  379. }
  380. /* Initialize AX.25 entry in arp device table */
  381. /* General purpose AX.25 frame output */
  382. int
  383. sendframe(axp,cmdrsp,ctl,data)
  384. struct ax25_cb *axp;
  385. char cmdrsp;
  386. char ctl;
  387. struct mbuf *data;
  388. {
  389.      struct mbuf *hbp,*cbp,*htonax25();
  390.      int i;
  391.  
  392.      if(axp == NULLAX25 || axp->interface == NULLIF)
  393.           return -1;
  394.  
  395.      /* Add control field */
  396.      if((cbp = pushdown(data,1)) == NULLBUF){
  397.           free_p(data);
  398.           return -1;
  399.      }
  400.      cbp->data[0] = ctl;
  401.  
  402.      axp->addr.cmdrsp = cmdrsp;
  403.      /* Create address header */
  404.      if((hbp = htonax25(&axp->addr,cbp)) == NULLBUF){
  405.           free_p(cbp);
  406.           return -1;
  407.      }
  408.      /* The packet is all ready, now send it */
  409.      if(axp->interface->forw != NULLIF)
  410.           i = (*axp->interface->forw->raw)(axp->interface->forw,hbp);
  411.      else
  412.           i = (*axp->interface->raw)(axp->interface,hbp);
  413.  
  414.      return i;
  415. }
  416. axarp()
  417. {
  418.      int psax25(),setpath();
  419.  
  420.      memcpy(axbdcst,ax25_bdcst.call,ALEN);
  421.      axbdcst[ALEN] = ax25_bdcst.ssid;
  422.  
  423.      arp_init(ARP_AX25,AXALEN,PID_FIRST|PID_LAST|PID_IP,
  424.       PID_FIRST|PID_LAST|PID_ARP,axbdcst,psax25,setpath);
  425. }
  426.